package com.mkvld.appietijdenv2.cloud;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import com.mkvld.appietijdenv2.data.Preferences;
import com.mkvld.appietijdenv2.data.Shift;
import com.mkvld.appietijdenv2.databases.ShiftDatabase;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings.Secure;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;


/**
 * This class is used to sync the local shifts and settings with the server
 * @author Remco
 *
 */
public class SyncServiceV9 extends IntentService {
	private static final String TAG = "SyncService"; 
	private static JSONArray queue = new JSONArray();
	private static boolean syncFailed = false;
	public static final String SYNC_TYPE_SHIFTS = "appietijden_sync_shifts";
	public static final String SYNC_TYPE_PREFS = "appietijden_sync_prefs";

	public SyncServiceV9() {
		super(TAG);
	}

	
	public static void addCloudShift(Context context, Shift shift) {
		try {
			JSONObject json = shift.toJSON();
			json.put("type", "add");
			queue.put(json);
		} catch (Exception e) {
			Log.e(TAG, "Add CloudShift to queue failed with reason: " + e.getLocalizedMessage());
		}
		
		if (queue.length() == 1 || (queue.length() > 0 && syncFailed))
			syncFailed = false;
			planSync(context);
	}
	
	public static void deleteCloudShift(Context context, Shift shift) {
		try {
			JSONObject json = shift.toJSON();
			json.put("type", "delete");
			queue.put(json);
		} catch (Exception e) {
			Log.e(TAG, "Delete CloudShift to queue failed with reason: " + e.getLocalizedMessage());
		}
		
		if (queue.length() == 1 || (queue.length() > 0 && syncFailed))
			syncFailed = false;
			planSync(context);
	}
	
	public static void editCloudShift(Context context, Shift shift, Shift prev) {
		try {
			JSONObject json = shift.toJSON();
			json.put("type", "edit");
			json.put("prev_start", prev.getStart());
			json.put("prev_end", prev.getEnd());
			queue.put(json);
		} catch (Exception e) {
			Log.e(TAG, "Edit CloudShift to queue failed with reason: " + e.getLocalizedMessage());
		}
		
		if (queue.length() == 1 || (queue.length() > 0 && syncFailed))
			syncFailed = false;
			planSync(context);
	}
	
	private static void planSync(Context context) {
		context.startService(new Intent(context, SyncServiceV9.class));
	}
	
	@Override
	protected void onHandleIntent(Intent intent) {
		String type = intent.getStringExtra("type");
		if (type == null) {
			try {
				Thread.sleep(1000);
				if (queue.length() > 0) {
					HttpClient httpClient = new DefaultHttpClient();
					HttpPost post = new HttpPost("http://at.remcomokveld.nl/sync.shifts.php?user_id="+Preferences.getCloudId(getApplicationContext())
							+ "&origin="+Secure.getString(getContentResolver(), Secure.ANDROID_ID));
					post.setHeader("Content-Type", "application/json");
					post.setEntity(new StringEntity(queue.toString()));
					
					HttpResponse response = httpClient.execute(post);
					if (response.getStatusLine().getStatusCode() == 200) {
						String tmp = convertStreamToString(response.getEntity().getContent()); 
						Log.v(TAG, tmp);
						queue = new JSONArray();
					} else {
						Log.v(TAG, convertStreamToString(response.getEntity().getContent()));
						syncFailed = true;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else if (type.equals("sync_shifts")) {
			updateShifts(intent);
		} else if (type.equals("sync_prefs")) {
			updatePreferences();
		}
	}

	private void updatePreferences() {
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpGet get = new HttpGet("http://at.remcomokveld.nl/sync.prefs.php?user_id="+Preferences.getCloudId(getApplicationContext()));				
			HttpResponse response = httpClient.execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				String responseText = convertStreamToString(response.getEntity().getContent());
				 JSONObject prefData = new JSONObject(responseText);
				 Preferences.setContract(getApplicationContext(), prefData.getInt("contract"));
			}
		} catch (Exception e) {
			Log.e(TAG, "Pref sync failed with reason: "+e.getMessage());
		}
	}

	private void updateShifts(Intent intent) {
		try {
			JSONArray weekYears = new JSONArray(intent.getStringExtra("week_years"));
			for (int i = 0; i < weekYears.length(); i++) {
				String[] tmp = weekYears.getString(i).split("-");
				int year = Integer.parseInt(tmp[0]);
				int week = Integer.parseInt(tmp[1]);
				HttpClient httpClient = new DefaultHttpClient();
				HttpGet get = new HttpGet("http://at.remcomokveld.nl/sync.shifts.php?user_id="
						+ Preferences.getCloudId(getApplicationContext())
						+ "&year=" + year
						+ "&week=" + week);
				HttpResponse response = httpClient.execute(get);
				if (response.getStatusLine().getStatusCode() == 200) {
					JSONArray shifts = new JSONArray(convertStreamToString(response.getEntity().getContent()));
					ShiftDatabase.db.clearWeek(year, week);
					for (int j = 0; j < shifts.length(); j++) {
						JSONObject shift = shifts.getJSONObject(j);
						ShiftDatabase.db.addShift(new Shift(shift.getInt("year"), shift.getInt("week"), 
								shift.getInt("day"), shift.getDouble("start"), 
								shift.getDouble("end")));
					}
					update();
				}
			}
			
		} catch (Exception e) {
			Log.e(TAG, "Shift sync failed with reason: "+e.getMessage());
		}
	}
	
	private static String convertStreamToString(InputStream is) {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
 
        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
	
	private void update() {
		LocalBroadcastManager manager = LocalBroadcastManager.getInstance(getApplicationContext());
		manager.sendBroadcast(new Intent("appietijden.update"));
	}

}
